package it.tukano.fun;

/**
 * An immutable pair of values
 * @author pgi
 * @param <A> the type of the first element
 * @param <B> the type of the second element
 */
public class Tuple2<A, B> {

    /**
     * Instance creator (the compiler can infer argument types)
     * @param <A> the type of the first argument
     * @param <B> the type of the second argument
     * @param a the first element of the tuple
     * @param b the second element of the tuple
     * @return a new tuple2
     */
    public static <A, B> Tuple2<A, B> newInstance(A a, B b) {
        return new Tuple2<A, B>(a, b);
    }
    
    /** The first element */
    private final A a;

    /** The second element */
    private final B b;

    /**
     * Instance initializer
     */
    public Tuple2(A a, B b) {
        this.a = a;
        this.b = b;
    }

    /**
     * Returns true if both elements are != null
     * @return true if both elements are not null
     */
    public boolean isDefined() {
        return getA() != null && getB() != null;
    }


    /**
     * Applies a function to this tuple if isDefined is true
     * @param fun the function apply
     */
    public void ifDefined(Function1<Tuple2<A, B>, ?> fun) {
        if(isDefined()) fun.apply(this);
    }

    /**
     * The first element
     * @return the a
     */
    public A getA() {
        return a;
    }

    /**
     * The second element
     * @return the b
     */
    public B getB() {
        return b;
    }
}
